#include "list.h"
#include "klib.h"
#include "log.h"
#include "types.h"
void list_init(list_t *list)
{
    ASSERT(list != (list_t *)0);
    list->first = list->last = (list_node_t *)0;
    list->count              = 0;
}
void list_insert_first(list_t *list, list_node_t *node)
{
    ASSERT(list != (list_t *)0);
    ASSERT(node != (list_node_t *)0);
    node->next = list->first;
    node->prev = (list_node_t *)0;
    if (list_empty(list))
    {
        list->last = node;
    }
    else
    {
        list->first->prev = node;
    }
    list->first = node;
    list->count++;
}
void list_insert_last(list_t *list, list_node_t *node)
{
    ASSERT(list != (list_t *)0);
    ASSERT(node != (list_node_t *)0);
    node->next = (list_node_t *)0;
    node->prev = list->last;
    if (list_empty(list))
    {
        list->first = node;
    }
    else
    {
        list->last->next = node;
    }
    list->last = node;
    list->count++;
}
list_node_t *list_remove_first(list_t *list)
{
    if (list == (list_t *)0 || list_empty(list))
    {
        return (list_node_t *)0;
    }
    list_node_t *node = list->first;
    list->first       = node->next;
    if (list->first)
    {
        list->first->prev = (list_node_t *)0;
    }
    list->count--;
    node->prev = node->next = (list_node_t *)0;
    return node;
}
list_node_t *list_remove_last(list_t *list)
{
    if (list == (list_t *)0 || list_empty(list))
    {
        return (list_node_t *)0;
    }
    list_node_t *node = list->last;
    list->last        = node->prev;
    if (list->last)
    {
        list->last->next = (list_node_t *)0;
    }
    list->count--;
    node->prev = node->next = (list_node_t *)0;
    return node;
}
// node must be in the list, or bug happens and kernel broken
list_node_t *list_remove(list_t *list, list_node_t *node)
{
    if (list == (list_t *)0 || list_empty(list) || node == (list_node_t *)0)
    {
        return (list_node_t *)0;
    }
    if (node == list->first)
    {
        return list_remove_first(list);
    }
    if (node == list->last)
    {
        return list_remove_last(list);
    }
    node->prev->next = node->next;
    node->next->prev = node->prev;
    list->count--;
    node->prev = node->next = (list_node_t *)0;
    return node;
}
void list_traverse(list_t *list, void (*func)(list_node_t *node))
{
    ASSERT(list != (list_t *)0);
    ASSERT(func != (void (*)(list_node_t *node))0);
    list_node_t *node = list->first;
    while (node != (list_node_t *)0)
    {
        func(node);
        node = node->next;
    }
}